package com.srolorz.fmtp.thread.pool.executor.pool;

import com.srolorz.fmtp.thread.pool.executor.exception.ThreadExecuteException;
import com.srolorz.fmtp.thread.pool.executor.factory.AbstractThreadFactory;
import org.apache.commons.lang.StringUtils;

import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.TimeUnit;

/**
 * @author eleven
 */
public class ThreadPoolManageEntity {
    private String threadGroupName;
    private String threadNamePrefix;
    private int corePoolSize;
    private int maxPoolSize;
    private long keepAliveTime;
    private TimeUnit timeUnit;
    private int workQueueSize;
    private BlockingQueue<Runnable> workQueue;
    private AbstractThreadFactory threadFactory;
    private RejectedExecutionHandler handler;
    private ThreadGroup threadGroup;

    public ThreadPoolManageEntity() {
    }

    public ThreadPoolManageEntity(int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit timeUnit, int workQueueSize) {
        this.check(corePoolSize, maxPoolSize);
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;
        this.keepAliveTime = keepAliveTime == 0L ? 60L : keepAliveTime;
        this.timeUnit = timeUnit == null ? TimeUnit.SECONDS : timeUnit;
        this.workQueueSize = workQueueSize > 0  ? workQueueSize : 20;
        this.workQueue = (BlockingQueue) (this.workQueue == null ? new LinkedBlockingDeque(this.workQueueSize) : this.workQueue);
    }

    public ThreadPoolManageEntity(String threadNamePrefix, int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit timeUnit, int workQueueSize) {
        this.check(corePoolSize, maxPoolSize);
        this.threadNamePrefix = threadNamePrefix;
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;
        this.keepAliveTime = keepAliveTime == 0L ? 60L : keepAliveTime;
        this.timeUnit = timeUnit == null ? TimeUnit.SECONDS : timeUnit;
        this.workQueueSize = workQueueSize > 0  ? workQueueSize : 20;
        this.workQueue = (BlockingQueue) (this.workQueue == null ? new LinkedBlockingDeque(this.workQueueSize) : this.workQueue);
    }

    private void check(int corePoolSize, int maxPoolSize) {
        if (corePoolSize == 0 || maxPoolSize == 0) {
            String msg = String.format("corePoolSize or maxPoolSize can not be zero! corePoolSize=%s, maxPoolSize=%s", corePoolSize, maxPoolSize);
            throw new ThreadExecuteException(msg);
        }
    }

    public String getThreadGroupName() {
        return threadGroupName;
    }

    public ThreadPoolManageEntity setThreadGroupName(String threadGroupName) {
        this.threadGroupName = threadGroupName;
        if (StringUtils.isNotBlank(this.threadGroupName)) {
            this.threadGroup = new ThreadGroup(this.threadGroupName);
        }
        return this;
    }

    public String getThreadNamePrefix() {
        return threadNamePrefix;
    }

    public ThreadPoolManageEntity setThreadNamePrefix(String threadNamePrefix) {
        this.threadNamePrefix = threadNamePrefix;
        return this;
    }

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public ThreadPoolManageEntity setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
        return this;
    }

    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    public ThreadPoolManageEntity setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
        return this;
    }

    public long getKeepAliveTime() {
        return keepAliveTime;
    }

    public ThreadPoolManageEntity setKeepAliveTime(long keepAliveTime) {
        this.keepAliveTime = keepAliveTime;
        return this;
    }

    public TimeUnit getTimeUnit() {
        return timeUnit;
    }

    public ThreadPoolManageEntity setTimeUnit(TimeUnit timeUnit) {
        this.timeUnit = timeUnit;
        return this;
    }

    public int getWorkQueueSize() {
        return workQueueSize;
    }

    public ThreadPoolManageEntity setWorkQueueSize(int workQueueSize) {
        this.workQueueSize = workQueueSize;
        return this;
    }

    public BlockingQueue<Runnable> getWorkQueue() {
        return workQueue;
    }

    public ThreadPoolManageEntity setWorkQueue(BlockingQueue<Runnable> workQueue) {
        this.workQueue = workQueue;
        return this;
    }

    public AbstractThreadFactory getThreadFactory() {
        return threadFactory;
    }

    public ThreadPoolManageEntity setThreadFactory(AbstractThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
        return this;
    }

    public RejectedExecutionHandler getHandler() {
        return handler;
    }

    public ThreadPoolManageEntity setHandler(RejectedExecutionHandler handler) {
        this.handler = handler;
        return this;
    }

    public ThreadGroup getThreadGroup() {
        return threadGroup;
    }

    public ThreadPoolManageEntity setThreadGroup(ThreadGroup threadGroup) {
        this.threadGroup = threadGroup;
        return this;
    }
}
